Skip to content

Conversation

@hauntsaninja
Copy link
Collaborator

@hauntsaninja hauntsaninja commented Feb 5, 2026


if isinstance(typ, UnionType):
type_ranges = [self.get_type_range_of_type(item) for item in typ.items]
is_upper_bound = any(t.is_upper_bound for t in type_ranges if t is not None)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 5, 2026

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

@hauntsaninja hauntsaninja requested a review from JukkaL February 5, 2026 22:59
t = get_proper_type(t)
if isinstance(t, UnionType):
return [b for a in t.items for b in flatten_types_if_tuple(a)]
return [UnionType.make_union([b for a in t.items for b in flatten_types_if_tuple(a)])]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, why the recursive flatten_types_if_tuple here? Maybe I'm misunderstanding, but my impression was that was for the 2nd arg of isinstance -- in which case this fails at runtime: int | (str,).

Copy link
Collaborator Author

@hauntsaninja hauntsaninja Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why the recursive flatten_types_if_tuple here?

See #20677

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in which case this fails at runtime: int | (str,)

See #20675

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah thanks for the reference. However, I don't see why the UnionType.make_union then... e.g., if I have final class A and isinstance w/ (A,) or (B, C), I would assume the type range for A should not have the is_upper_bound?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand... could you spell out the test case?

Copy link
Collaborator

@A5rocks A5rocks Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I'm unable to articulate that into a test case... However I noticed this seems wrong:

from __future__ import annotations
from typing import final

@final
class A: ...

class B: ...

class C: ...

def f1(x: A | C, t: type[A] | type[B]):
    if isinstance(x, t):
        reveal_type(x)  # N: Revealed type is "__main__.A"
    else:
        reveal_type(x)  # Revealed type is "__main__.A | __main__.C"

Specifically, I think the positive branch should be A | <subclass of C and B>, because t could be type[B]...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like that isn't relevant to this PR though!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants